//--------------------------------------------------------------------------------
// This file is part of the Windows Workflow Foundation Sample Code
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is intended only as a supplement to Microsoft
// Development Tools and/or on-line documentation.  See these other
// materials for detailed information regarding Microsoft code samples.
// 
// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//--------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.Serialization;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Collections;
using Microsoft.Samples.Workflow.UI;

namespace Microsoft.Samples.Workflow.UI.Design
{
    [ActivityDesignerTheme(typeof(InteractionGroupDesignerTheme))]
    class InteractionGroupDesigner : ParallelActivityDesigner 
	{
        ActivityDesignerVerbCollection designerVerbs;

        protected override CompositeActivity OnCreateNewBranch()
        {
            return new InteractionActivity();
        }

        public override bool CanInsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
        {
            foreach (Activity activity in activitiesToInsert)
            {
                if (!(activity is InteractionActivity) && !(activity is Navigator))
                {
                    return false;
                }
            }
            return base.CanInsertActivities(insertLocation, activitiesToInsert);
        }

        public override bool CanRemoveActivities(ReadOnlyCollection<Activity> activitiesToRemove)
        {
            if (activitiesToRemove == null)
            {
                throw new ArgumentNullException("activitiesToRemove");
            }

            if ((ContainedDesigners.Count - activitiesToRemove.Count) < 2)
            {
                return false;
            }
            else
            {
                return base.CanRemoveActivities(activitiesToRemove);
            }
        }

        protected override void PreFilterProperties(IDictionary properties)
        {
            base.PreFilterProperties(properties);

            InteractionGroupActivity interactionActivity = this.Activity as InteractionGroupActivity;
            if (interactionActivity == null)
            {
                throw new InvalidOperationException(SR.GetString(SR.Error_UnexpectedObjectType, "Activity", typeof(InteractionGroupActivity).FullName));
            }

            ArrayList keys = new ArrayList(properties.Keys);
            foreach (object key in keys)
            {
                PropertyDescriptor propDesc = properties[key] as PropertyDescriptor;
                if (propDesc.Name == "ReceiveInput" || propDesc.Name == "ActivityInputType")
                {
                    properties[key] = new ReadonlyPropertyDescriptor(propDesc);
                }
            }
        }

        protected override ActivityDesignerVerbCollection Verbs
        {
            get
            {
                ActivityDesignerVerbCollection verbs = new ActivityDesignerVerbCollection();
                verbs.AddRange(base.Verbs);

                if (this.designerVerbs == null)
                {
                    this.designerVerbs = new ActivityDesignerVerbCollection();
                    this.designerVerbs.Add(new ActivityDesignerVerb(this, DesignerVerbGroup.General, SR.GetString(SR.AddNavigator), new EventHandler(OnAddNavigator), new EventHandler(OnStatusAddBranch)));
                }

                verbs.AddRange(this.designerVerbs);
                return verbs;
            }
        }

        void OnStatusAddBranch(object sender, EventArgs e)
        {
            ActivityDesignerVerb verb = sender as ActivityDesignerVerb;
            if (verb != null)
            {
                verb.Enabled = IsEditable;
            }
        }

        void OnAddNavigator(object sender, EventArgs e)
        {
            CompositeActivity branchActivity = new Navigator();
            CompositeActivity compositeActivity = Activity as CompositeActivity;
            if (compositeActivity != null && branchActivity != null)
            {
                // Record the current number of child activities
                int designerCount = ContainedDesigners.Count;

                CompositeActivityDesigner.InsertActivities(this, new ConnectorHitTestInfo(this, HitTestLocations.Designer, compositeActivity.Activities.Count), new List<Activity>(new Activity[] { branchActivity }).AsReadOnly(), SR.GetString(SR.AddingBranch, branchActivity.GetType().Name));

                // If the number of child activities has increased, the branch add was successful, so
                // make sure the highest indexed branch is visible
                if (ContainedDesigners.Count > designerCount && ContainedDesigners.Count > 0)
                {
                    ContainedDesigners[ContainedDesigners.Count - 1].EnsureVisible();
                }
            }
        }

        class InteractionGroupDesignerTheme : CompositeDesignerTheme
        {
            internal const float WatermarkTransparency = 0.25f;
            internal const int ArcDiameter = 8;

            public InteractionGroupDesignerTheme(WorkflowTheme theme)
                : base(theme)
            {
                this.ShowDropShadow = false;
                this.ConnectorStartCap = LineAnchor.DiamondAnchor;
                this.ConnectorEndCap = LineAnchor.ArrowAnchor;
                this.ForeColor = Color.FromArgb(0xFF, 0x10, 0x10, 0x10);
                this.BorderColor = Color.FromArgb(0xFF, 0x49, 0x77, 0xb4);
                this.BorderStyle = DashStyle.Dash;
                this.BackColorStart = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xDF);
                this.BackColorEnd = Color.FromArgb(0xFF, 0xA9, 0xA3, 0xFF);
            }
        }
    }
}
